! git log -1 --format="%H"
aa9dbe508f9a5c056061345264537c2844a78a74
import sys
# Install gurobi
!{sys.executable} -m pip install -i https://pypi.gurobi.com gurobipy
!{sys.executable} -m pip install plotly geopy
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pandas as pd
from itertools import product
import gurobipy as gp
from gurobipy import GRB, quicksum
# These are ours
import problem
import visualization
Looking in indexes: https://pypi.gurobi.com Requirement already satisfied: gurobipy in /opt/anaconda3/lib/python3.8/site-packages (9.1.1) Requirement already satisfied: plotly in /opt/anaconda3/lib/python3.8/site-packages (4.14.3) Requirement already satisfied: geopy in /opt/anaconda3/lib/python3.8/site-packages (2.1.0) Requirement already satisfied: six in /opt/anaconda3/lib/python3.8/site-packages (from plotly) (1.15.0) Requirement already satisfied: retrying>=1.3.3 in /opt/anaconda3/lib/python3.8/site-packages (from plotly) (1.3.3) Requirement already satisfied: geographiclib<2,>=1.49 in /opt/anaconda3/lib/python3.8/site-packages (from geopy) (1.50)
def normalize(i, j):
assert i != j
return (i, j) if i < j else (j, i)
from model import Autonomax, Config
# Run on the first |C| cities (mostly for testing)
C = 41
# What scenario we will be utilizing
scenario = 0
# The number of cities in the core net
NC = 8
# 1 if the core net should be a cycle; 0 if it shoul be a path.
Z = 1
autonomax = Autonomax(
Config(
cities=problem.cities[:C],
distances=problem.D[:C, :C],
demand=problem.B[scenario][:C],
core_city_count=NC,
core_net_is_cycle=Z,
)
)
Academic license - for non-commercial use only - expires 2021-05-15 Using license file /Users/sjurwold/gurobi.lic
A = autonomax.model.getA()
count = lambda d: len(d) if isinstance(d, gp.tupledict) else 1
V = sum(count(v) for v in autonomax.variables.values())
C = sum(count(c) for c in autonomax.constraints.values())
print(f'V = {V}, C = {C}')
fig, ax = plt.subplots(1, figsize=(128, 128 * C/V))
ax.set_xticklabels([])
ax.set_yticklabels([])
plt.spy(A)
total = 0
print(f'\nCONSTRAINT SETS:')
for (name, constraint) in autonomax.constraints.items():
constraints_in_set = count(constraint)
print(f'{constraints_in_set:>5} | {name}')
#plt.gcf().text(0.07, 0.69 - 0.4 * (total + 0.5 * count(constraint)) / C, name, fontsize=14)
total += constraints_in_set
plt.plot([0, V], [total - 0.5, total - 0.5], color='grey')
total = 0
print(f'\nVARIABLE SETS:')
for (name, variables) in autonomax.variables.items():
variables_in_set = count(variables)
print(f'{variables_in_set:>5} | {name}')
#plt.gcf().text(0.1 + 0.8 * (total + 0.5*count(variables)) / V, 0.8, name, fontsize=14)
total += count(variables)
plt.plot([total - 0.5, total - 0.5], [0, C], color='grey')
plt.savefig('constraint-matrix.png', dpi=200)
V = 16277, C = 9597
CONSTRAINT SETS:
1 | one_control_center
41 | control_city_directly_connected
1681 | reduce_control_center_symmetry
41 | core_city_ub
1 | cycle_or_path
41 | disallow_core_tree
1 | exactly_nc_core_cities
41 | control_center_is_connected
5740 | is_connectable
287 | is_connected_timestep
41 | connected_graph
41 | conservation_of_flow
820 | force_edge_if_flow
820 | edge_cost_lb
VARIABLE SETS:
41 | is_control_center
820 | is_core_edge
41 | is_core_city
328 | is_connected_step
11767 | is_connectable_step
820 | flow
820 | abs_flow
820 | is_sub_edge
820 | edge_cost
autonomax.model.Params.timeLimit = 600.0
autonomax.model.optimize()
Changed value of parameter timeLimit to 600.0
Prev: inf Min: 0.0 Max: inf Default: inf
Gurobi Optimizer version 9.1.1 build v9.1.1rc0 (mac64)
Thread count: 8 physical cores, 8 logical processors, using up to 8 threads
Optimize a model with 9597 rows, 16277 columns and 50307 nonzeros
Model fingerprint: 0x4cc45383
Model has 8 SOS constraints
Model has 820 general constraints
Variable types: 2460 continuous, 13817 integer (13817 binary)
Coefficient statistics:
Matrix range [1e+00, 2e+05]
Objective range [1e+00, 2e+04]
Bounds range [1e+00, 1e+02]
RHS range [7e-01, 4e+01]
Presolve removed 112 rows and 6103 columns
Presolve time: 0.16s
Presolved: 9485 rows, 10174 columns, 49895 nonzeros
Variable types: 2460 continuous, 7714 integer (7714 binary)
Found heuristic solution: objective 119321.55212
Root relaxation: objective 3.326973e+03, 4914 iterations, 0.22 seconds
Nodes | Current Node | Objective Bounds | Work
Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time
0 0 3326.97264 0 196 119321.552 3326.97264 97.2% - 0s
H 0 0 92863.383829 3326.97264 96.4% - 0s
H 0 0 68397.560244 3326.97264 95.1% - 0s
H 0 0 33527.204073 3326.97264 90.1% - 0s
0 0 4957.57303 0 357 33527.2041 4957.57303 85.2% - 1s
H 0 0 33354.854381 4957.57303 85.1% - 1s
0 0 5673.15305 0 355 33354.8544 5673.15305 83.0% - 1s
0 0 5673.86859 0 358 33354.8544 5673.86859 83.0% - 1s
0 0 5674.07090 0 359 33354.8544 5674.07090 83.0% - 1s
0 0 5685.70098 0 421 33354.8544 5685.70098 83.0% - 1s
H 0 0 32668.531504 5685.70098 82.6% - 1s
0 0 5685.70098 0 396 32668.5315 5685.70098 82.6% - 1s
0 0 5685.70098 0 372 32668.5315 5685.70098 82.6% - 1s
0 0 5690.93613 0 465 32668.5315 5690.93613 82.6% - 1s
H 0 0 32376.599754 5690.93613 82.4% - 1s
0 0 5695.60139 0 382 32376.5998 5695.60139 82.4% - 1s
0 0 5699.10397 0 335 32376.5998 5699.10397 82.4% - 2s
0 0 5699.41427 0 428 32376.5998 5699.41427 82.4% - 2s
H 0 0 31942.820184 5699.41427 82.2% - 2s
H 0 0 30753.064095 5699.41427 81.5% - 2s
0 0 5704.51383 0 405 30753.0641 5704.51383 81.5% - 2s
H 0 0 30598.036353 5704.51383 81.4% - 2s
0 0 5704.76179 0 424 30598.0364 5704.76179 81.4% - 2s
0 0 5705.31890 0 435 30598.0364 5705.31890 81.4% - 2s
H 0 0 30523.312607 5705.31890 81.3% - 2s
H 0 0 30192.492805 5705.31890 81.1% - 2s
H 0 0 26745.750239 5705.31890 78.7% - 2s
0 0 5705.81456 0 413 26745.7502 5705.81456 78.7% - 2s
H 0 0 26253.853753 5705.81456 78.3% - 2s
0 0 5706.89020 0 481 26253.8538 5706.89020 78.3% - 3s
0 0 5706.89020 0 293 26253.8538 5706.89020 78.3% - 3s
H 0 0 24689.151050 5706.89020 76.9% - 3s
H 0 0 24656.690503 5706.89020 76.9% - 3s
0 2 5706.89020 0 282 24656.6905 5706.89020 76.9% - 4s
H 31 40 24594.048913 6044.43974 75.4% 672 4s
H 32 40 23996.901776 6044.43974 74.8% 654 4s
39 48 6134.31198 7 305 23996.9018 6044.43974 74.8% 612 5s
H 71 80 23944.260186 6044.43974 74.8% 420 5s
H 71 80 23685.153280 6044.43974 74.5% 420 5s
H 108 113 23675.153280 6044.43974 74.5% 358 6s
H 109 113 23671.883436 6044.43974 74.5% 356 6s
H 245 237 22087.713678 6044.43974 72.6% 246 7s
H 247 237 20041.548942 6044.43974 69.8% 244 7s
H 390 386 19789.406327 6044.43974 69.5% 211 8s
H 398 386 19644.237724 6044.43974 69.2% 209 8s
H 401 386 19582.182248 6044.43974 69.1% 209 8s
H 530 460 19567.695808 6044.43974 69.1% 200 9s
H 538 460 19561.616094 6044.43974 69.1% 200 9s
H 628 574 19547.129654 6044.43974 69.1% 192 9s
H 638 574 19547.129645 6044.43974 69.1% 191 9s
721 702 7636.68049 93 262 19547.1296 6044.43974 69.1% 179 10s
1630 1443 12862.7097 83 293 19547.1296 6044.43974 69.1% 122 16s
1638 1448 8902.00742 15 328 19547.1296 6044.43974 69.1% 121 20s
1649 1456 11130.5301 5 507 19547.1296 6044.43974 69.1% 120 25s
1660 1463 11846.1125 164 472 19547.1296 6044.43974 69.1% 119 30s
1670 1470 8910.15820 72 495 19547.1296 6254.78737 68.0% 119 35s
1674 1475 6264.91683 12 412 19547.1296 6264.91683 67.9% 180 45s
1676 1477 6264.91683 13 474 19547.1296 6264.91683 67.9% 184 51s
1686 1486 6264.91683 15 412 19547.1296 6264.91683 67.9% 193 56s
1710 1500 6327.23832 17 415 19547.1296 6264.91683 67.9% 209 60s
1767 1530 7432.55428 20 314 19547.1296 6264.91683 67.9% 232 65s
1851 1566 7859.34346 24 331 19547.1296 6264.91683 67.9% 249 70s
H 1948 1511 19461.681117 6264.91683 67.8% 262 74s
H 1952 1440 19247.640840 6264.91683 67.5% 263 74s
1955 1449 15056.8688 27 336 19247.6408 6264.91683 67.5% 264 75s
H 1980 1392 19176.766969 6264.91683 67.3% 269 76s
H 1998 1347 19031.929571 6264.91683 67.1% 272 77s
H 2005 1284 19019.189479 6264.91683 67.1% 273 77s
H 2008 1226 18998.396669 6264.91683 67.0% 273 77s
H 2012 1170 18959.053640 6264.91683 67.0% 273 77s
H 2067 1162 18957.038442 6264.91683 67.0% 276 79s
2112 1171 8635.65947 32 292 18957.0384 6264.91683 67.0% 278 80s
2315 1261 8979.31053 37 304 18957.0384 6264.91683 67.0% 289 85s
2584 1335 9656.83072 46 230 18957.0384 6264.91683 67.0% 299 91s
2822 1416 13333.7544 67 214 18957.0384 6264.91683 67.0% 315 96s
3049 1496 15882.0543 95 99 18957.0384 6918.29338 63.5% 323 100s
3226 1490 7885.01447 21 319 18957.0384 6918.29338 63.5% 328 105s
H 3291 1494 18957.038433 6918.29338 63.5% 333 110s
H 3349 1402 18207.038442 6918.29338 62.0% 334 110s
H 3350 1206 16708.889286 6918.29338 58.6% 334 110s
3518 1239 10312.3076 18 364 16708.8893 7108.04440 57.5% 345 116s
3728 1293 cutoff 33 16708.8893 7427.81813 55.5% 343 120s
3864 1363 8461.68687 22 352 16708.8893 7433.50232 55.5% 346 125s
4058 1419 9772.79632 42 267 16708.8893 7433.50232 55.5% 347 130s
4288 1495 8757.40346 23 349 16708.8893 7460.45443 55.4% 349 136s
4434 1627 14033.2422 41 292 16708.8893 7460.45443 55.4% 356 142s
4605 1661 14894.5702 51 299 16708.8893 7460.45443 55.4% 357 145s
4789 1867 10260.9017 28 326 16708.8893 7626.06899 54.4% 362 151s
4943 1922 infeasible 51 16708.8893 7831.43490 53.1% 362 155s
5275 2165 13438.1739 23 351 16708.8893 8068.89399 51.7% 364 161s
5493 2302 cutoff 34 16708.8893 8136.52664 51.3% 362 165s
5876 2493 10921.9649 53 233 16708.8893 8265.74013 50.5% 365 172s
H 5991 2493 16708.889271 8265.74013 50.5% 367 172s
6041 2538 9661.83004 29 265 16708.8893 8265.74013 50.5% 368 177s
6158 2662 10914.6476 31 244 16708.8893 8417.53708 49.6% 373 180s
6374 2772 10520.2118 37 285 16708.8893 8527.96709 49.0% 375 185s
H 6444 2772 16708.889268 8549.86104 48.8% 375 185s
6605 2936 14498.7447 32 270 16708.8893 8582.18241 48.6% 375 191s
6892 3046 13535.4265 44 199 16708.8893 8604.15680 48.5% 373 195s
7120 3120 infeasible 27 16708.8893 8683.89873 48.0% 377 200s
7345 3227 cutoff 31 16708.8893 8766.78472 47.5% 381 205s
7577 3310 16257.9287 25 359 16708.8893 8833.92072 47.1% 385 211s
7788 3511 10294.8033 49 298 16708.8893 8928.70141 46.6% 389 215s
8128 3600 12053.1406 26 380 16708.8893 8952.78254 46.4% 389 220s
8256 3725 cutoff 29 16708.8893 8957.63936 46.4% 392 226s
8522 3817 15284.7737 33 317 16708.8893 9032.03175 45.9% 396 231s
H 8667 3817 16708.889245 9051.59324 45.8% 397 231s
8762 3845 11366.3337 43 202 16708.8892 9076.11523 45.7% 399 238s
8894 4097 14347.4012 37 228 16708.8892 9084.01637 45.6% 398 245s
9345 4350 infeasible 58 16708.8892 9121.54141 45.4% 394 252s
H 9346 4350 16708.889239 9121.54141 45.4% 394 252s
H 9403 4350 16708.889216 9121.54141 45.4% 396 252s
9752 4575 9373.66345 61 373 16708.8892 9131.29273 45.4% 393 261s
H10101 4575 16708.889202 9168.76660 45.1% 393 261s
10149 4668 13724.3085 38 247 16708.8892 9168.76660 45.1% 393 269s
H10341 4668 16708.889199 9194.91098 45.0% 393 269s
10386 4870 16555.7118 35 304 16708.8892 9200.43068 44.9% 393 276s
H10762 4971 16708.889190 9265.88664 44.5% 396 283s
H10819 4971 16708.889169 9267.33705 44.5% 399 283s
H10928 4971 16708.889158 9294.99627 44.4% 399 283s
H10997 5216 16708.889131 9307.11088 44.3% 400 292s
11419 5349 11760.3464 26 314 16708.8891 9394.64032 43.8% 398 301s
11810 5614 12201.9446 45 307 16708.8891 9439.71911 43.5% 399 309s
H12017 5614 16708.889116 9447.33095 43.5% 398 309s
12299 5925 11501.5436 37 294 16708.8891 9468.07561 43.3% 399 316s
12804 6247 12296.0497 30 307 16708.8891 9516.28431 43.0% 399 324s
H12805 6247 16708.889113 9516.28431 43.0% 399 324s
H12868 6247 16708.889104 9516.81299 43.0% 399 324s
H13207 6247 16708.889059 9523.00503 43.0% 398 324s
13323 6440 14305.0238 31 268 16708.8891 9571.43924 42.7% 398 332s
13898 6611 10789.5383 37 300 16708.8891 9619.78195 42.4% 399 342s
H14337 6865 16708.889031 9619.78195 42.4% 402 353s
H14416 6865 16708.889027 9628.26212 42.4% 403 353s
H14532 6865 16708.889013 9661.72988 42.2% 403 353s
14958 7101 11853.7361 26 369 16708.8890 9721.91751 41.8% 401 364s
15570 7411 15766.0762 39 263 16708.8890 9771.06937 41.5% 402 373s
H15835 7411 16708.889002 9788.00664 41.4% 402 373s
16220 7698 cutoff 33 16708.8890 9851.47943 41.0% 402 383s
H16327 7698 16708.888989 9851.47943 41.0% 402 383s
16861 7792 10077.2503 43 292 16708.8890 9888.32033 40.8% 402 397s
H17039 8076 16708.888976 9888.32033 40.8% 400 408s
H17138 8076 16708.888961 9917.98551 40.6% 400 408s
H17248 8076 16708.888929 9937.89746 40.5% 400 408s
H17352 8076 16708.888896 9956.73356 40.4% 399 408s
H17628 8279 16708.888889 9967.75222 40.3% 402 421s
H17878 8279 16708.888879 10006.5463 40.1% 403 421s
H18055 8279 16708.888867 10025.5091 40.0% 405 421s
H18194 8541 16708.888763 10058.9776 39.8% 406 433s
18834 8815 13124.1039 24 347 16708.8888 10124.7591 39.4% 409 446s
H19514 8999 16708.888745 10157.1341 39.2% 412 461s
H19540 8999 16708.888732 10157.1341 39.2% 413 461s
H19941 8999 16708.888729 10185.0608 39.0% 410 461s
20067 9448 13097.0966 24 341 16708.8887 10207.0443 38.9% 410 475s
20980 9954 15579.6566 36 310 16708.8887 10298.1374 38.4% 410 489s
22015 10266 13731.5403 61 92 16708.8887 10357.3364 38.0% 409 505s
22718 10606 14525.2078 25 316 16708.8887 10396.5626 37.8% 410 519s
23529 10978 13327.1659 30 326 16708.8887 10460.1856 37.4% 411 535s
24355 11372 cutoff 40 16708.8887 10514.5400 37.1% 410 551s
25123 11803 12384.7652 83 261 16708.8887 10547.8016 36.9% 411 572s
26051 12250 16379.7136 31 284 16708.8887 10602.7426 36.5% 411 586s
27041 12491 cutoff 38 16708.8887 10685.5218 36.0% 409 600s
Cutting planes:
Gomory: 34
Cover: 1225
Implied bound: 1
MIR: 435
Flow cover: 958
GUB cover: 96
Inf proof: 2
Zero half: 90
RLT: 419
Relax-and-lift: 35
Explored 27875 nodes (11418601 simplex iterations) in 600.02 seconds
Thread count was 8 (of 8 available processors)
Solution count 10: 16708.9 16708.9 16708.9 ... 16708.9
Time limit reached
Best objective 1.670888872899e+04, best bound 1.070523302708e+04, gap 35.9309%
city_info = pd.DataFrame(autonomax.city_info())
city_info
| Index | Name | IsCoreCity | IsControlCenter | Demand | IngoingFlow | OutgoingFlow | |
|---|---|---|---|---|---|---|---|
| 0 | 0 | Boden | False | False | 4.5 | 3.999998e+00 | 8.499998 |
| 1 | 1 | Borås | False | False | 0.7 | 1.220000e+01 | 12.899999 |
| 2 | 2 | Eskilstuna | True | False | 1.1 | 1.113000e+02 | 112.400000 |
| 3 | 3 | Falun | False | False | 2.3 | 0.000000e+00 | 2.300000 |
| 4 | 4 | Gävle | True | False | 1.0 | 3.950000e+01 | 40.500000 |
| 5 | 5 | Göteborg | False | False | 5.8 | 1.918465e-13 | 5.800000 |
| 6 | 6 | Halmstad | False | False | 3.4 | 2.200000e+00 | 5.600000 |
| 7 | 7 | Haparanda | False | False | 4.6 | 0.000000e+00 | 4.600000 |
| 8 | 8 | Helsingborg | False | False | 2.2 | 0.000000e+00 | 2.200000 |
| 9 | 9 | Hudiksvall | False | False | 3.9 | 2.740000e+01 | 31.300000 |
| 10 | 10 | Jönköping | False | False | 1.2 | 1.290000e+01 | 14.100000 |
| 11 | 11 | Kalmar | False | False | 4.0 | 1.600000e+00 | 5.600000 |
| 12 | 12 | Karlskrona | False | False | 1.6 | 0.000000e+00 | 1.600000 |
| 13 | 13 | Karlstad | False | False | 0.9 | 2.629008e-13 | 0.900000 |
| 14 | 14 | Kiruna | False | False | 4.0 | 0.000000e+00 | 3.999999 |
| 15 | 15 | Kristianstad | False | False | 3.0 | 3.900000e+00 | 6.899999 |
| 16 | 16 | Lidköping | False | False | 1.2 | 7.600000e+00 | 8.800000 |
| 17 | 17 | Linköping | False | False | 4.1 | 3.910000e+01 | 43.200000 |
| 18 | 18 | Luleå | False | False | 2.0 | 1.310000e+01 | 15.099999 |
| 19 | 19 | Malmö | False | False | 2.6 | 0.000000e+00 | 2.600000 |
| 20 | 20 | Motala | False | False | 2.4 | 1.130000e+01 | 13.700000 |
| 21 | 21 | Norrköping | True | False | 1.7 | 1.046000e+02 | 106.300000 |
| 22 | 22 | Nyköping | True | False | 4.6 | 4.940000e+01 | 54.000000 |
| 23 | 23 | Sandviken | True | False | 4.5 | 3.700001e+00 | 8.200001 |
| 24 | 24 | Skellefteå | False | False | 4.4 | 1.510000e+01 | 19.499999 |
| 25 | 25 | Skövde | False | False | 2.5 | 8.800000e+00 | 11.299999 |
| 26 | 26 | Stockholm | True | False | 7.0 | 4.240000e+01 | 49.400001 |
| 27 | 27 | Sundsvall | False | False | 0.7 | 2.670000e+01 | 27.400000 |
| 28 | 28 | Trelleborg | False | False | 1.3 | 0.000000e+00 | 1.300000 |
| 29 | 29 | Uddevalla | False | False | 4.0 | 3.979039e-13 | 4.000000 |
| 30 | 30 | Umeå | False | False | 3.2 | 1.950000e+01 | 22.699999 |
| 31 | 31 | Uppsala | True | False | 1.9 | 4.050000e+01 | 42.400000 |
| 32 | 32 | Varberg | False | False | 0.8 | 5.600000e+00 | 6.400000 |
| 33 | 33 | Vetlanda | False | False | 2.1 | 9.199999e+00 | 11.300000 |
| 34 | 34 | Vänersborg | False | False | 3.6 | 4.000000e+00 | 7.600000 |
| 35 | 35 | Västervik | False | False | 1.8 | 5.600000e+00 | 7.400000 |
| 36 | 36 | Västerås | True | True | 1.4 | 1.124000e+02 | 1.400001 |
| 37 | 37 | Växjö | False | False | 2.3 | 6.899999e+00 | 9.199999 |
| 38 | 38 | Örebro | False | False | 4.1 | 8.999999e-01 | 5.000000 |
| 39 | 39 | Örnsköldsvik | False | False | 3.1 | 2.270000e+01 | 25.799999 |
| 40 | 40 | Östersund | False | False | 0.9 | 7.460699e-13 | 0.900000 |
edge_info = pd.DataFrame(autonomax.edge_info())
edge_info
| From | To | Type | Flow | Cost | Distance | |
|---|---|---|---|---|---|---|
| 0 | Skellefteå | Umeå | SUB | 19.499999 | 731.139126 | 111 |
| 1 | Eskilstuna | Västerås | CORE | 112.400000 | 430.000000 | 43 |
| 2 | Gävle | Hudiksvall | SUB | -31.300000 | 1278.724559 | 118 |
| 3 | Norrköping | Nyköping | CORE | -54.000000 | 580.000000 | 58 |
| 4 | Nyköping | Stockholm | CORE | -49.400000 | 900.000000 | 90 |
| 5 | Linköping | Norrköping | SUB | 43.200000 | 408.715170 | 44 |
| 6 | Boden | Kiruna | SUB | -3.999998 | 637.912738 | 291 |
| 7 | Linköping | Vetlanda | SUB | -11.300000 | 589.291375 | 138 |
| 8 | Sundsvall | Östersund | SUB | -0.900000 | 70.870179 | 166 |
| 9 | Kalmar | Västervik | SUB | 5.600000 | 300.208553 | 139 |
| 10 | Halmstad | Helsingborg | SUB | -2.200000 | 58.849859 | 79 |
| 11 | Umeå | Örnsköldsvik | SUB | 22.699999 | 849.479911 | 111 |
| 12 | Lidköping | Skövde | SUB | 8.800000 | 105.450189 | 49 |
| 13 | Eskilstuna | Örebro | SUB | -5.000000 | 129.560337 | 83 |
| 14 | Karlstad | Örebro | SUB | 0.900000 | 29.229967 | 77 |
| 15 | Halmstad | Varberg | SUB | 5.600000 | 102.802153 | 65 |
| 16 | Lidköping | Vänersborg | SUB | -7.600000 | 121.696732 | 60 |
| 17 | Motala | Skövde | SUB | -11.299999 | 468.037920 | 118 |
| 18 | Uddevalla | Vänersborg | SUB | 4.000000 | 22.172758 | 21 |
| 19 | Gävle | Sandviken | CORE | -8.200000 | 250.000000 | 25 |
| 20 | Hudiksvall | Sundsvall | SUB | -27.400000 | 641.652310 | 81 |
| 21 | Sandviken | Västerås | CORE | -1.400001 | 1100.000000 | 110 |
| 22 | Linköping | Motala | SUB | -13.700000 | 167.788674 | 51 |
| 23 | Borås | Göteborg | SUB | -5.800000 | 119.727508 | 71 |
| 24 | Jönköping | Linköping | SUB | 14.100000 | 633.137863 | 125 |
| 25 | Sundsvall | Örnsköldsvik | SUB | -25.799999 | 1177.683846 | 127 |
| 26 | Kristianstad | Malmö | SUB | -2.600000 | 84.931621 | 94 |
| 27 | Borås | Varberg | SUB | -6.400000 | 165.811280 | 84 |
| 28 | Vetlanda | Växjö | SUB | -9.199999 | 187.740561 | 72 |
| 29 | Kristianstad | Trelleborg | SUB | -1.300000 | 53.600690 | 104 |
| 30 | Haparanda | Luleå | SUB | 4.600000 | 210.858567 | 124 |
| 31 | Luleå | Skellefteå | SUB | 15.099999 | 742.410198 | 133 |
| 32 | Stockholm | Uppsala | CORE | -42.400000 | 690.000000 | 69 |
| 33 | Kristianstad | Växjö | SUB | 6.899999 | 296.827592 | 120 |
| 34 | Norrköping | Västervik | SUB | -7.400000 | 287.369522 | 112 |
| 35 | Falun | Sandviken | SUB | 2.300000 | 48.115171 | 65 |
| 36 | Gävle | Uppsala | CORE | 40.500000 | 600.000000 | 60 |
| 37 | Kalmar | Karlskrona | SUB | -1.600000 | 45.527165 | 79 |
| 38 | Borås | Jönköping | SUB | 12.899999 | 312.907804 | 82 |
| 39 | Boden | Luleå | SUB | 8.499998 | 58.656830 | 32 |
| 40 | Eskilstuna | Norrköping | CORE | -106.300000 | 1020.000000 | 102 |
core_cost = sum(edge_info[edge_info['Type'] == 'CORE']['Cost'])
subnet_cost = sum(edge_info[edge_info['Type'] == 'SUB']['Cost'])
total_cost = core_cost + subnet_cost
print(f'core = {core_cost:>9.3f}')
print(f'subnet = {subnet_cost:>9.3f}')
print('------------------')
print(f'total = {total_cost:>9.3f}')
assert abs(autonomax.model.getObjective().getValue() - total_cost) < 1e-6
core = 5570.000 subnet = 11138.889 ------------------ total = 16708.889
visualization.show(pd.DataFrame(autonomax.city_info()), pd.DataFrame(autonomax.edge_info()))